// Package middleware
// @Author Spume
// @Date 2024-05-09 16:23

package api

import (
	"context"
	"encoding/base64"
	"net/http"

	"gitee.com/spume/toolkit/utils/ccode"
	"github.com/gogf/gf/v2/crypto/gaes"
	"github.com/gogf/gf/v2/encoding/gjson"
	"github.com/gogf/gf/v2/errors/gerror"
	"github.com/gogf/gf/v2/frame/g"
	"github.com/gogf/gf/v2/net/ghttp"
)

// DefaultHandlerResponse is the default implementation of HandlerResponse.
type DefaultHandlerResponse struct {
	Code    int         `json:"code"    dc:"Error code"`
	Message string      `json:"message" dc:"Error message"`
	Details interface{} `json:"details,omitempty" dc:"Error details"`
	Data    interface{} `json:"data"    dc:"Result data for certain request according API definition"`
}

// MiddlewareHandlerResponse is the default middleware handling handler response object and its error.
func MiddlewareHandlerResponse(r *ghttp.Request) {
	r.Middleware.Next()

	// There's custom buffer content, it then exits current handler.
	if r.Response.BufferLength() > 0 &&
		r.Response.Status != http.StatusInternalServerError &&
		r.Response.Status != http.StatusOK {
		return
	}

	var (
		msg  string = "OK"
		err         = r.GetError()
		res         = r.GetHandlerResponse()
		code        = gerror.Code(err)
	)
	if err != nil {
		if code == ccode.CodeNil || code.Code() < 400 {
			code = ccode.CodeInternalError
		}

		msg = err.Error()
	} else {
		if r.Response.Status > 0 && r.Response.Status != http.StatusOK {
			msg = http.StatusText(r.Response.Status)
			switch r.Response.Status {
			case http.StatusNotFound:
				code = ccode.CodeNotFound
			case http.StatusForbidden:
				code = ccode.CodeNotAuthorized
			default:
				code = ccode.CodeUnknown
			}
			// It creates error as it can be retrieved by other middlewares.
			err = gerror.NewCode(code, msg)
			r.SetError(err)
		} else {
			code = ccode.CodeOK
			if r.GetCtxVar("encrypt").Bool() {
				res = AES(r.Context(), res)
			}
		}
	}

	if g.IsNil(res) {
		res = struct{}{}
	}
	var details interface{}
	if code.Code() == ccode.CodeInternalError.Code() || r.GetQuery("debug").Bool() {
		details = gerror.Stack(err)
	}

	r.Response.SetBuffer(nil)

	r.Response.WriteJson(DefaultHandlerResponse{
		Code:    code.Code(),
		Message: msg,
		Details: details,
		Data:    res,
	})
}

func AES(ctx context.Context, data any) (str string) {

	// 解析原始JSON
	jd := gjson.New(data)

	// 将data字段转为字节数组
	dataBytes := []byte(jd.String())

	// AES加密密钥，必须是16、24或32字节长度
	key := g.Cfg().MustGet(ctx, "APP.key").Bytes()
	g.Cfg().MustGet(ctx, "")

	// 可选的初始化向量
	iv := g.Cfg().MustGet(ctx, "APP.iv").Bytes() // 16字节IV 16字节密钥示例

	// 加密data字段
	encryptedData, err := gaes.Encrypt(dataBytes, key, iv)
	if err != nil {
		g.Log().Debugf(ctx, "加密失败: %v\n", err)
		return
	}

	// 将加密后的数据转为Base64字符串
	str = base64.StdEncoding.EncodeToString(encryptedData)
	return
}
